<?php
Zend::loadClass('Lead_EDO_Datatype_Relation');

class Lead_EDO_Datatype_Relation_HasAndBelongsToMany extends Lead_EDO_Datatype_Relation
{
   	
   	
   	private $_className;
    private $_assocObj;
    private $_joinTable;
    private $_value;
    private $_keys;
    private $_options;
    
   	
    public function __construct(Lead_EDO_Object_Abstract $owner, $config = array())
    {
        parent::__construct($owner, $config);	
    
        $this->_foreignKey = $config['foreign_key'];
        $this->_className = $config['class_name'];
    
        $this->_joinTable = (isset($config['join_table'])) ? $config['join_table'] : $config;
        
        $this->_config = $config;
                
        if(is_array($this->_joinTable))
        {
            $jtArr = array($this->getOwner()->getClass(), $this->_config['class_name']);
            sort($jtArr);
            $first = array_shift($jtArr);
            if($first == $this->getOwner()->getClass())
            {
                $this->_joinTable = $this->getOwner()->getClass() . '_' . $this->_joinTable['name'] . '_' . $this->_joinTable['class_name'] . '_' . $this->_joinTable['foreign_key'];
            }
            else 
            {
                $this->_joinTable = $this->_joinTable['class_name'] . '_' . $this->_joinTable['foreign_key'] . '_' . $this->getOwner()->getClass() . '_' . $this->_joinTable['name'];
            }
            
        }

	    
	    
	    $this->getOwner()->attach($this, 'afterFetch', '_afterFetchActions');
        $this->getOwner()->attach($this, 'onSaveSuccess', '_save');
        $this->getOwner()->attach($this, 'onInsertSuccess', '_save');
        
        
    }
	
    
    public function setValue($value, $validate = true)
    {
        if($validate)
            $value = $this->validate($value);
                
        if(is_array($value))
        {
            $this->_keys = $value;
            $this->_value = null;
            return true;
        }
        
        return ($value === false) ? false : true;
        
    }
    
    
    public function getDefaultValue()
    {
        return array();
    }
    
    
    public function validate($value)
    {
           
        if(!is_array($value))
        {
            $value = explode(',', $value);
            foreach($value as $key => &$valRef)
            {
                $valRef = trim($valRef);
            }
                
        }
        
        if(isset($value['faker']))
        {
            $value = (isset($value['values'])) ? $value['values'] : array();
        }
                
        $options = $this->getOptions();
        
        $validated = array();
        foreach($value as $key => &$valRef)
        {
            if(key_exists($valRef, $options))
            {
                $validated[] = $valRef;
            }
            elseif($theKey = array_search($valRef, $options))
            {
                $validated[] = $theKey;
            }
        }
                        
        return $validated;
    }
    
    
    public function getJoinTable()
    {
        return $this->_joinTable;
    }
    
    
    public function _save()
    {
        if(!is_null($this->_keys))
        {
            
            $this->getOwner()->ldb->beginTransAction();

            $phrase = "DELETE FROM {$this->_joinTable} WHERE {$this->getOwner()->getClass()}_id = {$this->getOwner()->id}";
            
            $this->getOwner()->ldb->exec($phrase);
            
            // print "<hr />";
            
            $phrase = "INSERT INTO {$this->_joinTable} ({$this->getOwner()->getClass()}_id, {$this->getOwner()->edo->get($this->getClassName())->getClass()}_id) VALUES (?, ?)";
            
            // print $phrase;
            
            $prepared = $this->getOwner()->ldb->prepare($phrase);
            foreach($this->_keys as $key)
            {
                $prepared->execute(array($this->getOwner()->id, $key));
            }
            $prepared->closeCursor();
            
                        
                                               
            
            $this->getOwner()->ldb->commit();
            
            return true;
         
        }
                
    }
    
    
	
	public function _afterFetchActions()
	{
  	    $this->_value = null;
	}
	
	
	
	public function isNull()
	{
	    return (is_null($this->_foreignKeyValue));
	}
	
	
	
	public function getClass()
	{
	    $relClasses = $this->getOwner()->getRelationsClasses();
	    return $relClasses[$this->getName()];
	}
	
	
	public function getValue()
	{
	    	    	    	    
	    if(!$this->_value)
  	    {
    	    
  	        $myClass = $this->getClass();
  	          	        
  	        $obj = $this->getOwner()->edo->get($this->_className);
      	    $obj->getFinder()->addJoin($this->_joinTable, 'INNER', "{$this->getClass()}_id = {$this->getOwner()->id} AND {$this->_className}_id = edo.id");
      	    
      	    if($this->getConfig('order'))
      	         $obj->getFinder()->addOrderer($this->getConfig('order'));
      	      	    
      	    $this->_value = $obj->getFinder()->findAll(array());
            // return $this->_value;	    

  	    }	    
	    return $this->_value;
	    
	}
	
	
	public function getOptions()
    {
                       
        if(!isset(Lead_EDO::$relationOptions[$this->getOwner()->getClass()][$this->getName()]))
	    {
	        
	       $args = $this->parseConditionsToValues();
           $obj = $this->getOwner()->getHandler()->get($this->getClassName());
	       
           if($this->getConfig('order'))
           {
               $obj->getFinder()->addOrderer($this->getConfig('order'));
           }
           
           if(!$this->getConfig('use_slow_method'))
           {
               $query = $obj->getFinder()->getQuery();
                                     
               $display = $this->getConfig('display');
               $regexp = "/(\%([a-zA-Z_]*))/si";
               preg_match_all($regexp, $display, $fields);
               $fields = $fields[2];
               $fields = array_unique($fields);
               foreach($fields as $field)
               {
                   $table = $obj->getFieldsTable($field);
                   
                   $query->addField("{$table}.{$field}", false);
                                                 
                   if(!$query->tableIsJoined($table))
                        $query->addJoin($table, 'INNER', "edo.id = {$table}.id");
               }
              
               $result = $query->ldb->fetchAll($query->getSQL());
               
               
               
               $opzions = array();
               foreach($result as $row)
               {
                   $display2 = $display;
                   foreach($fields as $field)
                   {
                        $display2 = str_ireplace("%{$field}", $row[$field], $display2);
                   }
                   $opzions[$row['id']] = $display2;
               }
    
    
               
                  
           }
           else 
           {
           
                $options = $obj->getFinder()->findAll($args, false, 'fast2');
                
                $opzions = array();
                foreach($options as $obj)
                {
                $opzions[$obj->id] = $this->resolveTags($obj, $this->getConfig('display'));
                }
                
                  
           }
           
           
           
	        Lead_EDO::$relationOptions[$this->getOwner()->getClass()][$this->getName()] = $opzions;

	    }
	    
	    return Lead_EDO::$relationOptions[$this->getOwner()->getClass()][$this->getName()];
        	    
	}

	
	public function joinTo(Query $query)
	{
	    	    
	    
	    
	    $obj = $this->getOwner()->getHandler()->get($this->getClassName());
	    
	    
	    $clausule = $this->getOwner()->getFirstTable() . '.id = ' . $this->_joinTable . '.' . $this->getOwner()->getClass() . '_id' ;
	    	    
	    $query->addJoin($this->_joinTable, 'INNER', $clausule);
	    	    
	    
	    $tables = $obj->getTables();
        $firstTable = array_shift($tables);
                       
                
        $query->addJoin($firstTable, 'INNER', "{$this->_joinTable}.{$obj->getClass()}_id = {$firstTable}.id");
                        
        foreach($tables as $table)
        {
            $query->addJoin($table, 'INNER', "{$firstTable}.id = {$table}.id");
        }

	    
	    
	}

	
	public function getOpposite()
	{
	    return $this->getConfig('class_name') . '_' . $this->getForeignKey();
	    	    	    
	}
	

    
}
